/*
 * Copyright (c) 2006-2025, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-08-27     RT-Thread    first version
 * 经确认 显示屏是好的 能够正常背光 解析来就是移植了 移植lvgl版本
 */

#include <rtthread.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "main.h"
#include "gpio.h"
#include "spi.h"
#include "lvgl.h"
//#include "lvgl_conf.h"

/* 引脚定义（根据你的硬件配置） */
#define LCD_CS_LOW()   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)  // PA4为片选
#define LCD_CS_HIGH()  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
#define LCD_DC_CMD()   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET)  // DC为PB1
#define LCD_DC_DATA()  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET)
#define LCD_RST_LOW()  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET)  // RST为PB0
#define LCD_RST_HIGH() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET)
#define LCD_LED_ON()   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET)   // 背光控制

/* RGB565颜色定义 */
#define RED     0xF800
#define GREEN   0x07E0
#define BLUE    0x001F
#define WHITE   0xFFFF
#define BLACK   0x0000
#define YELLOW  0xFFE0
#define PURPLE  0xF81F

/* SPI发送函数（带超时处理） */
static uint8_t LCD_SPI_Transmit(uint8_t *data, uint16_t len) {
  if (HAL_SPI_Transmit(&hspi1, data, len, 100) != HAL_OK) {
    return 0; // 发送失败
  }
  return 1; // 发送成功
}

static void LCD_WriteCommand(uint8_t cmd) {
  LCD_CS_LOW();
  LCD_DC_CMD();
  LCD_SPI_Transmit(&cmd, 1);
  LCD_CS_HIGH();
  // 只在需要长延时的命令后加延时（比如0x01软复位、0x11睡眠退出），其他命令去掉延时
  if(cmd == 0x01 || cmd == 0x11) {
    HAL_Delay(1);  // 仅软复位、睡眠退出需要延时
  }
}

/* 写入数据 */
static void LCD_WriteData(uint8_t data) {
  LCD_CS_LOW();
  LCD_DC_DATA();               // 数据模式
  LCD_SPI_Transmit(&data, 1);
  LCD_CS_HIGH();
}

/* 写入16位颜色数据 */
static void LCD_WriteColorData(uint16_t color) {
  uint8_t data[2] = {color >> 8, color & 0xFF}; // 高8位在前
  LCD_CS_LOW();
  LCD_DC_DATA();
  LCD_SPI_Transmit(data, 2);
  LCD_CS_HIGH();
}

/* 设置显示区域（TLI9341分辨率为240×320） */
void LCD_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
  // 设置列地址
  LCD_WriteCommand(0x2A);
  LCD_WriteData(x0 >> 8);
  LCD_WriteData(x0 & 0xFF);
  LCD_WriteData(x1 >> 8);
  LCD_WriteData(x1 & 0xFF);

  // 设置行地址
  LCD_WriteCommand(0x2B);
  LCD_WriteData(y0 >> 8);
  LCD_WriteData(y0 & 0xFF);
  LCD_WriteData(y1 >> 8);
  LCD_WriteData(y1 & 0xFF);

  // 准备写入GRAM
  LCD_WriteCommand(0x2C);
}

/* TLI9341初始化序列（关键！与ILI9341兼容但需严格时序） */
void LCD_Init(void) {
  // 1. 开启背光
  LCD_LED_ON();
  HAL_Delay(50);

  // 2. 硬件复位
  LCD_RST_LOW();
  HAL_Delay(100);  // 至少100ms复位时间
  LCD_RST_HIGH();
  HAL_Delay(200);  // 等待复位完成

  // 3. 初始化命令序列（针对TLI9341优化）
  LCD_WriteCommand(0x01);  // 软复位
  HAL_Delay(150);

  LCD_WriteCommand(0xCF);  // 电源控制B
  LCD_WriteData(0x00);
  LCD_WriteData(0xC1);
  LCD_WriteData(0x30);
  HAL_Delay(5);

  LCD_WriteCommand(0xED);  // 电源启动控制
  LCD_WriteData(0x64);
  LCD_WriteData(0x03);
  LCD_WriteData(0x12);
  LCD_WriteData(0x81);
  HAL_Delay(5);

  LCD_WriteCommand(0xE8);  // 驱动时序控制A
  LCD_WriteData(0x85);
  LCD_WriteData(0x00);
  LCD_WriteData(0x78);
  HAL_Delay(5);

  LCD_WriteCommand(0xCB);  // 电源控制A
  LCD_WriteData(0x39);
  LCD_WriteData(0x2C);
  LCD_WriteData(0x00);
  LCD_WriteData(0x34);
  LCD_WriteData(0x02);
  HAL_Delay(5);

  LCD_WriteCommand(0xF7);  // 泵浦控制
  LCD_WriteData(0x20);
  HAL_Delay(5);

  LCD_WriteCommand(0xEA);  // 驱动时序控制B
  LCD_WriteData(0x00);
  LCD_WriteData(0x00);
  HAL_Delay(5);

  LCD_WriteCommand(0xC0);  // 功率控制1
  LCD_WriteData(0x23);
  HAL_Delay(5);

  LCD_WriteCommand(0xC1);  // 功率控制2
  LCD_WriteData(0x10);
  HAL_Delay(5);

  LCD_WriteCommand(0xC5);  // VCOM控制1
  LCD_WriteData(0x3E);
  LCD_WriteData(0x28);
  HAL_Delay(5);

  LCD_WriteCommand(0xC7);  // VCOM控制2
  LCD_WriteData(0x86);
  HAL_Delay(5);

  LCD_WriteCommand(0x36);  // 内存数据访问控制（设置屏幕方向）
  LCD_WriteData(0x48);     // 横屏模式（0x08为竖屏，根据实际调整）
  HAL_Delay(5);

  LCD_WriteCommand(0x3A);  // 像素格式设置
  LCD_WriteData(0x05);     // 16位RGB565格式（必须设置）
  HAL_Delay(5);

  LCD_WriteCommand(0xB1);  // 帧速率控制（正常模式）
  LCD_WriteData(0x00);
  LCD_WriteData(0x18);
  HAL_Delay(5);

  LCD_WriteCommand(0xB6);  // 显示功能控制
  LCD_WriteData(0x08);
  LCD_WriteData(0x82);
  LCD_WriteData(0x27);
  HAL_Delay(5);

  LCD_WriteCommand(0x11);  // 睡眠退出
  HAL_Delay(120);

  LCD_WriteCommand(0x29);  // 显示开启
  HAL_Delay(50);
}

/* 全屏填充颜色 */
void LCD_FillScreen(uint16_t color) {
  LCD_SetWindow(0, 0, 239, 319);  // TLI9341全屏范围（240×320）

  // 连续写入所有像素（优化写入效率）
  LCD_CS_LOW();
  LCD_DC_DATA();
  for (uint32_t i = 0; i < 240 * 320; i++) {
    uint8_t data[2] = {color >> 8, color & 0xFF};
    LCD_SPI_Transmit(data, 2);
  }
  LCD_CS_HIGH();
}
extern void lv_port_disp_init(void);
/*
 * 画点函数：在坐标 (x, y) 绘制颜色为 color 的像素
 * 实现逻辑：先设置窗口为单个点 (x,y)，再写入颜色数据
 */
void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color) {
    // 1. 设置显示窗口为单个点 (x,y)
    LCD_SetWindow(x, y, x, y);  // 窗口左上角和右下角都是 (x,y)，即单个点
    // 2. 写入该点的颜色数据
    LCD_WriteColorData(color);
}

int main(void) {
  HAL_Init();
  MX_SPI1_Init();    // 确保SPI配置正确（CPOL=0, CPHA=0, 速率≤10MHz）
  MX_GPIO_Init();

  LCD_Init();        // 初始化屏幕

  lv_init();
  /*
  //LCD初始化//lvgl初始化//1vg1与LCD接口初始化//lvgl demo测试
  //问题就出在下面这个地方 怎么解决 呢
  //不是 我操了 他妈的到底跑哪去了这内存 怎么一个函数会占200kb呢？
  // 独立的标签
  lv_obj_t *myLabel =lv_label_create(lv_scr_act());
  lv_label_set_text(myLabel, "Hello world!");
  lv_obj_align(myLabel,LV_ALIGN_CENTER,0,0);
  */
  lv_port_disp_init();
  ui_init();
  // 强制 LVGL 渲染全屏红色（测试用）
  /*
     lv_obj_t *scr = lv_scr_act();
     lv_obj_set_style_bg_color(scr, lv_color_hex(0xF800), 0); // 红色背景
     lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);           // 不透明

  lv_obj_t *myLabel = lv_label_create(lv_scr_act());
  lv_label_set_text(myLabel, "Hello world!");
  // 强制使用 dejavu_10 字体（确保该字体已启用）
  lv_obj_set_style_text_font(myLabel, &lv_font_montserrat_14, 0);
  lv_obj_align(myLabel, LV_ALIGN_CENTER, 0, 0);
  */
  // 在 main 函数中添加，测试硬件能否绘制小区域
  // 创建画布控件
  // 创建一个红色块（替代手动硬件绘制）
  /*
  lv_obj_t *red_block = lv_obj_create(lv_scr_act());
  lv_obj_set_size(red_block, 50, 50);          // 宽50，高10
  lv_obj_set_pos(red_block, 100, 150);         // 位置(x=100, y=150)
  lv_obj_set_style_bg_color(red_block, lv_color_hex(0xF800), 0); // 红色背景
  lv_obj_set_style_bg_opa(red_block, LV_OPA_COVER, 0);           // 不透明

  lv_obj_t *myLabel = lv_label_create(lv_scr_act());
  if(myLabel == NULL) {
      rt_kprintf("标签创建失败！可能内存不足！\n"); // 调试：检查是否内存不足
  }
  lv_label_set_text(myLabel,LV_SYMBOL_MUTE "hello world");
  //真他妈挺逆天的 非得加个符号才能用  说不定真是字符类型的问题 得查看查看
  //lv_label_set_text(myLabel, LV_SYMBOL_OK "123"); // 显示对勾符号
  // 强制设置极简字体（确保已启用）
  lv_obj_set_style_text_font(myLabel, &lv_font_montserrat_14, 0);
  // 显式设置文字颜色（与背景对比，如黑色）
  lv_obj_set_style_text_color(myLabel, lv_color_hex(0x0000), 0);
  lv_obj_align(myLabel, LV_ALIGN_CENTER, 0, 0); // 居中
  //LCD_FillScreen(RED);

  //确实是内存问题 现在需要220kb给这个函数
 // lv_demo_benchmark();
   */
  // 循环显示不同颜色，便于观察
  while (1) {
      // 必须添加LVGL事件处理，否则界面不会刷新
      //

      lv_timer_handler();
/*
    LCD_FillScreen(RED);
    HAL_Delay(1000);
    LCD_FillScreen(GREEN);
    HAL_Delay(1000);
    LCD_FillScreen(BLUE);
    HAL_Delay(1000);
    LCD_FillScreen(YELLOW);
    HAL_Delay(1000);
    LCD_FillScreen(PURPLE);
    HAL_Delay(1000);
    LCD_FillScreen(WHITE);
    HAL_Delay(1000);*/
    rt_thread_mdelay(5);
  }
}
